package com.sj.purchase.modules.cost.config.task.synchronizedata;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sj.purchase.modules.cost.domain.WarehouseEnum;
import com.sj.purchase.modules.cost.domain.order.InOrder;
import com.sj.purchase.modules.cost.domain.order.InOrderItem;
import com.sj.purchase.modules.cost.domain.order.OutOrder;
import com.sj.purchase.modules.cost.domain.order.OutOrderItem;
import com.sj.purchase.modules.cost.repository.order.InOrderRepository;
import com.sj.purchase.modules.cost.repository.order.OutOrderRepository;
import com.sj.purchase.util.DateUtils;
import com.sj.purchase.util.StockUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 入库出库
 * Created by yangrd on 2017/7/22.
 */
@Component
class OrderTask2 {

    private static final Logger logger = LoggerFactory.getLogger(OrderTask2.class);

    @Autowired
    private RestTemplate restTemplate;

    @Value("${sj.ecwms}")
    private String ecwmsApi;

    @Autowired
    private OutOrderRepository outOrderRepository;

    @Autowired
    private InOrderRepository inOrderRepository;

    private static String FORMAT = "yyyy/MM/dd";

    /**
     * @param day yyyy/MM/dd
     */
    @Transactional
    public void synchronizeOutOrder(String day) {
        try {
            synchronizeOutOrder0(day);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    /**
     * @param day yyyy/MM/dd
     */
    @Transactional
    public void synchronizeInOrder(String day) {
        try {
            synchronizeInOrder0(day);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }


    private void synchronizeOutOrder0(String day) throws ParseException {
        Date tomorrow = DateUtils.addDays(DateUtils.parseDate(day, FORMAT), 1);
        String tomorrowStr = DateFormatUtils.format(tomorrow, FORMAT);
        //销售出库其他出库--发货订单
        String url1 = String.format("%s/shipping-order?start=%s&end=%s", ecwmsApi, day, tomorrowStr);
        JSONArray jsonArray1 = JSON.parseArray(restTemplate.getForObject(url1, String.class));
        List<OutOrder> shippingOrders = jsonArray1.stream().map(this::parseOutOrder).collect(Collectors.toList());
        logger.debug("销售出库其他出库 :=> {}", url1);
        //采购退货出库--退货订单
        String url2 = String.format("%s/purchase-return-order?start=%s&end=%s", ecwmsApi, day, tomorrowStr);
        JSONArray jsonArray2 = JSON.parseArray(restTemplate.getForObject(url2, String.class));
        List<OutOrder> procurementReturns = jsonArray2.stream().map(this::parseProcurementReturnsOutOrder).collect(Collectors.toList());
        logger.debug("采购退货出库 :=> {}", url2);
        procurementReturns.addAll(shippingOrders);
        List<OutOrder> outOrders = procurementReturns;
        outOrders = outOrders.stream().peek(outOrder -> {
            //合并订单号过长无法保存 与大庆讨论得到这种解决方式
            String orderNo = outOrder.getOrderNo();
            int index = orderNo.indexOf(",");
            if (index > 0) {
                outOrder.setOrderNo(orderNo.substring(0, index) + ".....");
            }
        }).collect(Collectors.toList());

        outOrders.forEach(outOrder -> {
            logger.debug("出库单:=> {}", JSON.toJSONString(outOrder));
            outOrderRepository.save(outOrder);
        });
        logger.debug("[出库数据同步完成] 订单数目:=> {}", outOrders.size());
    }


    private void synchronizeInOrder0(String day) throws ParseException {
        Date tomorrow = DateUtils.addDays(DateUtils.parseDate(day, FORMAT), 1);
        String tomorrowStr = DateFormatUtils.format(tomorrow, FORMAT);
        //采购入库 销售退货 --入库
        String url = String.format("%s/receipt-order?start=%s&end=%s", ecwmsApi, day, tomorrowStr);
        JSONArray jsonArray1 = JSON.parseArray(restTemplate.getForObject(url, String.class));
        List<InOrder> receiptOrders = jsonArray1.stream().map(this::parseInOrder).collect(Collectors.toList());
        logger.debug("采购入库 销售退货 入库订单 :=> {}", url);
        receiptOrders.forEach(inOrder -> {
            logger.debug("入库单:=> {}", JSON.toJSONString(inOrder));
            inOrderRepository.save(inOrder);
        });
        logger.debug("[入库数据同步完成] 订单数目:=> {}", receiptOrders.size());

    }


    //采购退货
    private OutOrder parseProcurementReturnsOutOrder(Object object) {
        JSONObject jsonObject = (JSONObject) object;
        String wmsId = jsonObject.getString("wmsId");
        String orderNo = jsonObject.getString("orderNo");
        Date orderDate = jsonObject.getDate("submitDate");
        OutOrder.OrderType orderType = OutOrder.OrderType.OUT_PROCUREMENT_RETURNS;
        WarehouseEnum warehouseEnum = StockUtils.getWarehouse(jsonObject.getString("warehouse"));

        OutOrder outOrder = buildOutOrderInstances(wmsId, orderNo, orderDate, orderType, warehouseEnum);
        JSONArray outOrderItemArray = jsonObject.getJSONArray("orderItems");
        Set<OutOrderItem> outOrderItemSet = parseOutOrderItemsByJSONFiled(outOrder, outOrderItemArray, "skuNo", "price", "qty");//todo 字段不存在price
        outOrder.setOrderItems(outOrderItemSet);
        return outOrder;

    }

    //销售出库其他出库
    private OutOrder parseOutOrder(Object object) {
        JSONObject jsonObject = (JSONObject) object;
        String wmsId = jsonObject.getString("wmsId");
        String orderNo = jsonObject.getString("orderNo");
        Date orderDate = jsonObject.getDate("deliveryTime");//记录发货时间
        OutOrder.OrderType orderType = jsonObject.getString("fromTypeName").equals("销售") ? OutOrder.OrderType.OUT_SALES : OutOrder.OrderType.OUT_OTHER;
        WarehouseEnum warehouseEnum = StockUtils.getWarehouse(jsonObject.getString("warehouse"));
        String shopName = jsonObject.getString("shopName");//店铺
        String buyerName = jsonObject.getString("buyerName");//买家姓名
        Double payment = jsonObject.getDouble("payment");//销售价


        OutOrder outOrder = buildOutOrderInstances(wmsId, orderNo, orderDate, orderType, warehouseEnum).setBuyerName(buyerName).setShopName(shopName).setPayment(payment);
        JSONArray outOrderItemArray = jsonObject.getJSONArray("orderItems");
        Set<OutOrderItem> outOrderItemSet = parseOutOrderItemsByJSONFiled(outOrder, outOrderItemArray, "skuNo", "price", "shippedQty");
        outOrder.setOrderItems(outOrderItemSet);
        return outOrder;
    }

    private OutOrder buildOutOrderInstances(String wmsId, String orderNo, Date orderDate, OutOrder.OrderType orderType, WarehouseEnum warehouseEnum) {
        OutOrder outOrder = new OutOrder();
        outOrder.setId(wmsId);
        outOrder.setOrderNo(orderNo == null ? "" : orderNo);
        outOrder.setSaveDateDay(DateUtils.getStartOfDay(orderDate));
        outOrder.setType(orderType);
        outOrder.setWarehouseEnum(warehouseEnum);
        outOrder.setCreateDate(orderDate);
        return outOrder;
    }

    private Set<OutOrderItem> parseOutOrderItemsByJSONFiled(OutOrder outOrder, JSONArray outOrderItemArray, String fSkuNo, String fPrice, String fNum) {
        return outOrderItemArray.stream().map(obj -> {
            JSONObject orderItem = (JSONObject) obj;
            String skuNo = orderItem.getString(fSkuNo);
            Double price = orderItem.getDouble(fPrice);
            Long num = orderItem.getLong(fNum);
            OutOrderItem outOrderItem = new OutOrderItem();
            outOrderItem.setSkuNo(skuNo);
            outOrderItem.setPrice(price);
            outOrderItem.setNum(num);
            outOrderItem.setTotalPrice(num * price);
            outOrderItem.setOrder(outOrder);
            return outOrderItem;
        }).collect(Collectors.toSet());
    }


    private InOrder parseInOrder(Object object) {
        JSONObject jsonObject = (JSONObject) object;
        String wmsId = jsonObject.getString("wmsId");
        String orderNo = jsonObject.getString("orderNo");
        Date orderDate = jsonObject.getDate("submitDate");
        String supplierName = jsonObject.getString("supplierName");
        InOrder.OrderType orderType = jsonObject.getString("fromTypeCode").equals("Purchase") ? InOrder.OrderType.IN_PURCHASE : InOrder.OrderType.IN_RETURN;
        WarehouseEnum warehouseEnum = StockUtils.getWarehouse(jsonObject.getString("warehouse"));


        InOrder inOrder = new InOrder();
        inOrder.setId(wmsId);
        inOrder.setOrderNo(orderNo == null ? "" : orderNo);
        inOrder.setSaveDateDay(DateUtils.getStartOfDay(orderDate));
        inOrder.setType(orderType);
        inOrder.setWarehouseEnum(warehouseEnum);
        inOrder.setCreateDate(orderDate);
        inOrder.setSupplierName(supplierName);

        JSONArray jsonArray = jsonObject.getJSONArray("orderItems");
        Set<InOrderItem> inOrderItemSet = jsonArray.stream().map(obj -> {
            JSONObject orderItem = (JSONObject) obj;
            String skuNo = orderItem.getString("skuNo");
            Double price = orderItem.getDouble("price");
            Long num = orderItem.getLong("receivedQty");

            InOrderItem inOrderItem = new InOrderItem();
            inOrderItem.setSkuNo(skuNo);
            inOrderItem.setPrice(price);
            inOrderItem.setNum(num);
            inOrderItem.setOrder(inOrder);
            return inOrderItem;
        }).collect(Collectors.toSet());

        inOrder.setOrderItems(inOrderItemSet);
        return inOrder;
    }

}
